home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1998 September / Macworld (1998-09).dmg / Shareware World / Info / For Developers / MacZoop 1.8.3 / More Classes / Advanced Dialogs / ZExtraDialogItems.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-12  |  31.6 KB  |  1,408 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            MacZoop - "the framework for the rest of us"             
  5. *
  6. *
  7. *
  8. *            ZExtraDialogItems.cpp    -- some other kinds of dialog item objects
  9. *
  10. *
  11. *            © 1997, Graham Cox
  12. *
  13. *
  14. *
  15. *************************************************************************************************/
  16.  
  17. #include    "ZExtraDialogItems.h"
  18. #include    "ZClipboard.h"
  19. #include    "MacZoop.h"
  20. #include    "xDEFJump.h"
  21. #include    "ZGrafState.h"
  22.  
  23. #include    <Palettes.h>
  24. #include    <LowMem.h>
  25. #include    <Icons.h>
  26.  
  27. // embedded LDEF function:
  28.  
  29. static pascal void    IconListBoxDefProc( short iMessage,
  30.                                         Boolean selected,
  31.                                         Rect* bounds, 
  32.                                         Cell theCell,
  33.                                         short dataOffset,
  34.                                         short dataLength,
  35.                                         ListHandle theList );
  36.  
  37. static void        DrawIconCell(     Rect* r,
  38.                                 IconInfo* info,
  39.                                 Boolean hilited,
  40.                                 Boolean showTitles,
  41.                                 IconHilite hStyle );
  42.  
  43. extern short    gFontMenuID;
  44.  
  45. #pragma mark ====== ZLineDialogItem =======
  46.  
  47. /*-------------------------------***  CONSTRUCTOR  ***----------------------------------*/
  48.  
  49. ZLineDialogItem::ZLineDialogItem( ZDialog* aDialog, short item )
  50.     : ZDialogItem( aDialog, item )
  51. {
  52.     itsType = plainLine;
  53.     patIndex = 0;
  54. }
  55.  
  56.  
  57. /*---------------------------------***  DRAWITEM  ***-----------------------------------*/
  58. /*    
  59. draw the line item according to its parameters
  60. ----------------------------------------------------------------------------------------*/
  61.  
  62. void    ZLineDialogItem::DrawItem()
  63. {
  64.     // draw the line using the style set. It is always 1 pixel wide (or 2 if 3D)
  65.     // and the longer dimension of the bounds sets the orientation.
  66.     
  67.     RGBColor    f, b, white = { 0xFFFF, 0xFFFF, 0xFFFF };
  68.     Boolean        isVert = (bounds.bottom - bounds.top) > (bounds.right - bounds.left);
  69.  
  70.     PenSize( 1, 1 );
  71.     
  72.     if ( itsType == patternLine )
  73.     {
  74.         Pattern        p;
  75.         
  76.         GetIndPattern( &p, sysPatListID, patIndex);
  77.         PenPat( &p );
  78.     }
  79.     else
  80.         PenPat( &qd.black );
  81.         
  82.     PenMode( patCopy );
  83.     MoveTo( bounds.left, bounds.top );
  84.     
  85.     // if a 3D line, establish the relevant colours based on the fore and back colours
  86.     // set for the window.
  87.     
  88.     if ( itsType == raised3DLine ||
  89.          itsType == etched3DLine )
  90.     {
  91.         GDHandle    bestDev;
  92.         Rect        r = bounds;
  93.         
  94.         GetForeColor( &f );
  95.         GetBackColor( &b );
  96.         
  97.         LocalToGlobal( &topLeft( r ));
  98.         LocalToGlobal( &botRight( r ));
  99.         
  100.         bestDev = GetMaxDevice( &r );
  101.         
  102.         GetGray( bestDev, &b, &f );
  103.         GetGray( bestDev, &white, &b );
  104.         
  105.         // draw the 3D lines. <f> is the darker colour, <b> is the lighter
  106.         
  107.         if ( isVert )
  108.         {
  109.             if (itsType == raised3DLine )
  110.                 RGBForeColor( &b );
  111.             else
  112.                 RGBForeColor( &f );
  113.                 
  114.             LineTo( bounds.left, bounds.bottom - 1 );
  115.             Move( 1, 0 );
  116.             
  117.             if (itsType == raised3DLine )
  118.                 RGBForeColor( &f );
  119.             else
  120.                 RGBForeColor( &b );
  121.                 
  122.             LineTo( bounds.left + 1, bounds.top );
  123.         }
  124.         else
  125.         {
  126.             if (itsType == raised3DLine )
  127.                 RGBForeColor( &b );
  128.             else
  129.                 RGBForeColor( &f );
  130.                 
  131.             LineTo( bounds.right - 1, bounds.top );
  132.             Move( 0, 1 );
  133.             
  134.             if (itsType == raised3DLine )
  135.                 RGBForeColor( &f );
  136.             else
  137.                 RGBForeColor( &b );
  138.                 
  139.             LineTo( bounds.left, bounds.top + 1 );
  140.         }
  141.     }
  142.     else
  143.     {
  144.         // a plain or patterned line
  145.     
  146.         if ( isVert )
  147.             LineTo( bounds.left, bounds.bottom - 1 );
  148.         else
  149.             LineTo( bounds.right - 1, bounds.top );
  150.     }
  151.     
  152.     PenNormal();
  153.     ForeColor( blackColor );
  154. }
  155.  
  156.  
  157. /*---------------------------------***  INITITEM  ***-----------------------------------*/
  158. /*    
  159. set up line parameters from original magic string params
  160. ----------------------------------------------------------------------------------------*/
  161.  
  162. void    ZLineDialogItem::InitItem( const long param1, const long param2 )
  163. {
  164.     itsType = ( LineType ) param1;
  165.     patIndex = param2;
  166. }
  167.  
  168.  
  169. #pragma mark -
  170. #pragma mark ======= ZIconListBox ========
  171.  
  172.  
  173. /*-------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  174.  
  175. ZIconListBox::ZIconListBox( ZDialog* aDialog, short item )
  176.     : ZListDialogItem( aDialog, item )
  177. {
  178.     showTitles = TRUE;
  179.     smallIcons = FALSE;
  180.     iHilite = iconDefaultHilite;
  181.     fontSize = 9;
  182.     font = kFontIDGeneva;
  183. }
  184.  
  185. /*--------------------------------***  DESTRUCTOR  ***---------------------------------*/
  186.  
  187. ZIconListBox::~ZIconListBox()
  188. {
  189.     if ( theList )
  190.     {
  191.         // dispose icons
  192.         
  193.         DisposeIconCells();
  194.         
  195.         // get rid of the embedded LDEF handle if it's there
  196.         
  197.         Handle    h = (*theList)->listDefProc;
  198.         
  199.         if ( h )
  200.         {
  201.             Cell    c = { 0, 0 };
  202.             
  203.             IconListBoxDefProc( lCloseMsg, FALSE, &bounds, c, 0, 0, theList );
  204.             DisposeHandle( h );
  205.         }
  206.         // important:
  207.             
  208.         (*theList)->listDefProc = NULL;
  209.     }
  210. }
  211.  
  212. /*---------------------------------***  INITITEM  ***-----------------------------------*/
  213. /*    
  214. set up icon listbox parameters from original magic string params
  215. ----------------------------------------------------------------------------------------*/
  216.  
  217. void        ZIconListBox::InitItem( const long param1, const long param2 )
  218. {
  219.     // make the list
  220.     
  221.     MakeMacList( param1 );
  222.     
  223.     // install the icons from the template
  224.     
  225.     if ( param1 > 0 )
  226.         AddIconCells( param1 );
  227.     
  228.     // do the usual trick of sizing the bounds to encompass a whole number
  229.     // of cells
  230.     
  231.     short    cellHeight = (*theList)->cellSize.v;
  232.     short    cellWidth  = (*theList)->cellSize.h;
  233.     short    adjustAmount;
  234.     Boolean    hasH, hasV;
  235.     
  236.     hasH = ((*theList)->hScroll != NULL);
  237.     hasV = ((*theList)->vScroll != NULL);
  238.     
  239.     adjustAmount = (bounds.bottom - bounds.top - (hasH? kStdScrollbarWidth + 2 : 2)) % cellHeight;
  240.     bounds.bottom -= adjustAmount;
  241.     
  242.     adjustAmount = (bounds.right - bounds.left - (hasV? kStdScrollbarWidth + 2 : 2)) % cellWidth;
  243.     bounds.right -= adjustAmount;
  244.     
  245.     LSize( bounds.right - bounds.left - (hasV? kStdScrollbarWidth + 2 : 2),
  246.            bounds.bottom - bounds.top - (hasH? kStdScrollbarWidth + 2 : 2),
  247.            theList );
  248.     
  249.     // ready to go, so activate the list appropriately
  250.     
  251.     LActivate( TRUE, theList );
  252.     ActivateListItem( FALSE );
  253. }
  254.  
  255.  
  256. void        ZIconListBox::DrawItem()
  257. {
  258.     Rect        r = bounds;
  259.     Boolean        hasH, hasV;
  260.     RGBColor    saveBack;
  261.     
  262.     hasH = ((*theList)->hScroll != NULL);
  263.     hasV = ((*theList)->vScroll != NULL);
  264.     
  265.     InsetRect( &r, 1, 1 );
  266.     
  267.     if ( hasH )
  268.         r.bottom -= kStdScrollbarWidth;
  269.         
  270.     if ( hasV )
  271.         r.right -= kStdScrollbarWidth;
  272.     
  273.     GetBackColor( &saveBack );    
  274.     BackColor( whiteColor );
  275.     ZListDialogItem::DrawItem();
  276.     
  277.     RGBBackColor( &saveBack );
  278. }
  279.  
  280.  
  281. /*--------------------------------***  APPENDICON  ***----------------------------------*/
  282. /*    
  283. append an icon to the list programmatically
  284. ----------------------------------------------------------------------------------------*/
  285.  
  286. void        ZIconListBox::AppendIcon( IconInfo* info )
  287. {
  288.     Cell        c;
  289.     Boolean     isHList = ((*theList)->hScroll != NULL) && ((*theList)->vScroll == NULL);
  290.  
  291.     // to make the titles look nicer when hilited, we add a space in front and another
  292.     // at the end of the title
  293.     
  294.     BackColor( whiteColor );
  295.     
  296.     LSetDrawingMode( FALSE, theList );
  297.     
  298.     BlockMoveData( &info->title[1], &info->title[2], info->title[0] );
  299.     info->title[1] = ' ';
  300.     info->title[0] += 2;
  301.     info->title[ info->title[0]] = ' ';
  302.  
  303.     c.h = (*theList)->dataBounds.right - 1;
  304.     c.v = (*theList)->dataBounds.bottom - 1;
  305.     
  306.     if ( isHList )
  307.     {
  308.         if ( c.v == -1 )
  309.             c.v = LAddRow( 1, c.v + 1, theList );
  310.         c.h = LAddColumn( 1, c.h + 1, theList );
  311.     }
  312.     else
  313.     {
  314.         if ( c.h == -1 )
  315.             c.h = LAddColumn( 1, c.h + 1, theList );
  316.         c.v = LAddRow( 1, c.v + 1, theList );
  317.     }
  318.     
  319.     LSetDrawingMode( TRUE, theList );
  320.     LSetCell( info, sizeof( IconInfo ), c, theList );
  321. }
  322.  
  323. /*-------------------------------***  MAKEMACLIST  ***----------------------------------*/
  324. /*    
  325. build the icon list structures. This is a normal List Manager list but using a custom
  326. LDEF that we have embedded within this source file. Each cell of the list contains an
  327. icon and optionally a title string below it. Layout can be horizontal or vertical.
  328. ----------------------------------------------------------------------------------------*/
  329.  
  330. void        ZIconListBox::MakeMacList( const short listTemplateID )
  331. {
  332.     Point                cellSize = { 34, 0 };
  333.     ListTemplateHdl        ltH;
  334.     IconListBoxHdl        lbH;
  335.     Rect                r, dataBounds = { 0, 0, 0, 0 };
  336.     Boolean                hasV = TRUE, hasH = FALSE;
  337.     ZDialog*            zd = (ZDialog*) GetBoss();
  338.     
  339.     // get the bounding box for this item
  340.     
  341.     r = bounds;
  342.     InsetRect( &r, 1, 1 );
  343.     
  344.     // see if there's a LIST template, which will define our font, etc
  345.     
  346.     if ( listTemplateID != 0 )
  347.     {
  348.         ltH = ( ListTemplateHdl ) GetResource( kListTemplateResType, listTemplateID );
  349.     
  350.         if ( ltH )
  351.         {
  352.             // there is a template, so use that to define the list.
  353.         
  354.             dataBounds.right     = (*ltH)->columns;
  355.             dataBounds.bottom     = (*ltH)->rows;
  356.             hasV                 = (*ltH)->hasVertScroll;
  357.             hasH                 = (*ltH)->hasHorizScroll;
  358.             canBeHandler         = (*ltH)->keyboardNav;
  359.             fontSize             = (*ltH)->fontSize;
  360.             strListID            = (*ltH)->stringsListID;
  361.             
  362.             GetFNum((*ltH)->fontName, &font );
  363.             
  364.             ReleaseResource((Handle) ltH );
  365.         }
  366.         
  367.         // get some basic settings from the ICLB resource
  368.         
  369.         lbH = (IconListBoxHdl) GetResource( kIconListTemplateResType, listTemplateID );
  370.         
  371.         if ( lbH )
  372.         {
  373.             showTitles = (*lbH)->addTitles;
  374.             iHilite = (IconHilite)(*lbH)->hiliteStyle;
  375.         
  376.             ReleaseResource((Handle) lbH );
  377.         }
  378.     }        
  379.     // allow space for the scrollbars we want
  380.     
  381.     if ( hasV )
  382.         r.right -= 15;
  383.         
  384.     if ( hasH )
  385.         r.bottom -= 15;
  386.         
  387.     // compute the cell height based on the size of an icon plus the current font
  388.     
  389.     if ( showTitles )
  390.     {
  391.         FontInfo    fi;
  392.         
  393.         GetFontInfo( &fi );
  394.         cellSize.v = 34 + fi.ascent + fi.descent + fi.leading;
  395.     }
  396.     
  397.     if ( hasH )
  398.         cellSize.h = 64;
  399.         
  400.     // make the list initally
  401.     
  402.     short    saveFont, saveSize;
  403.     
  404.     SetUpFontForList( &saveFont, &saveSize );
  405.     
  406.     theList = LNew( &r, &dataBounds, cellSize, 0, zd->GetMacWindow(), TRUE, FALSE, hasH, hasV );
  407.     FailNIL( theList );
  408.     
  409.     // now scrungle our cunning LDEF into it
  410.     
  411.     InstallIconLDEF();
  412.     
  413.     // now we just need to install all our icons, but we leave that to InitItem, which called
  414.     // this method in the first place
  415.     
  416.     if (font != 0 &&
  417.         fontSize != 0 )
  418.     {
  419.         TextFont( saveFont );
  420.         TextSize( saveSize );
  421.     }
  422.     
  423.     // by default, icon lists only allow one selection at a time (probably most common use)
  424.     // change this line or override for other behaviours.
  425.     
  426.     (*theList)->selFlags = lOnlyOne;
  427. }
  428.  
  429.  
  430. /*-----------------------------***  INSTALLICONLDEF  ***--------------------------------*/
  431. /*    
  432. set the list to use our embedded LDEF and make sure it's inited properly
  433. ----------------------------------------------------------------------------------------*/
  434.  
  435. void        ZIconListBox::InstallIconLDEF()
  436. {
  437.     Handle    ldefHand;
  438.     Rect    r = {0, 0, 0, 0};
  439.     Cell    aCell = { 0, 0 };
  440.     
  441.     FailNIL( ldefHand = GetUniversalFunctionHandle((ProcPtr) IconListBoxDefProc, uppListDefProcInfo ));
  442.     
  443.     (*theList)->listDefProc = ldefHand;
  444.     
  445.     // set the list's refcon to this so that the LDEF can callback into us if need be
  446.     
  447.     (*theList)->refCon = (long) this;
  448.     
  449.     // the "init" message won't have been sent, since it was inited using the system LDEF,
  450.     // so simply call it directly in case the LDEF does something here. 
  451.     
  452.     IconListBoxDefProc( lInitMsg, FALSE, &r, aCell, 0, 0, theList );
  453. }
  454.  
  455.  
  456. /*-------------------------------***  ADDICONCELLS  ***---------------------------------*/
  457. /*    
  458. read the icon listbox template and fetch all the icons, etc needed and set them up
  459. ----------------------------------------------------------------------------------------*/
  460.  
  461. void        ZIconListBox::AddIconCells( const short templateID )
  462. {
  463.     short            i;
  464.     Cell            c = { 0, 0 };
  465.     IconInfo        info;
  466.     IconListBoxHdl    lbH;
  467.     
  468.     // attempt to locate the template (ICLB) with the ID passed
  469.     
  470.     lbH = (IconListBoxHdl) GetResource( kIconListTemplateResType, templateID );
  471.     
  472.     if ( lbH )
  473.     {
  474.         // obtained the template, now construct the icon list
  475.         
  476.         for( i = 0; i < (*lbH)->numIcons; i++ )
  477.         {
  478.             // locate each icon and load it as needed
  479.             
  480.             info.iconID = (*lbH)->icons[i].resID;
  481.  
  482.             switch ((*lbH)->icons[i].iconType)
  483.             {
  484.                 case 0:        // plain black & white icon
  485.                     info.iType = IconPlain;
  486.                     info.theIcon = GetIcon( info.iconID );
  487.                     break;
  488.                 
  489.                 case 1:        // 'cicn' resource
  490.                     info.iType = IconColour;
  491.                     info.theIcon = (Handle) GetCIcon( info.iconID );
  492.                     break;
  493.                 
  494.                 case 2:        // indexed icon, etc
  495.                 default:
  496.                     info.iType = IconIndexed;
  497.                     info.theIcon = NULL;
  498.                     break;
  499.             }
  500.             
  501.             // get the title string from the relevant string list
  502.             
  503.             GetIndString( info.title, (*lbH)->titleListResID, (*lbH)->icons[i].nameIndex );
  504.             info.userData = 0;
  505.             
  506.             AppendIcon( &info );
  507.         }
  508.         ReleaseResource((Handle) lbH );
  509.     }
  510. }
  511.  
  512. /*-----------------------------***  DISPOSEICONCELLS  ***-------------------------------*/
  513. /*    
  514. disposes the icons when the list is closed
  515. ----------------------------------------------------------------------------------------*/
  516.  
  517. void    ZIconListBox::DisposeIconCells()
  518. {
  519.     Cell        c = {0, 0};
  520.     short        row, col, len;
  521.     IconInfo    info;
  522.     
  523.     for( col = 0; col < (*theList)->dataBounds.right; col++ )
  524.     {
  525.         for( row = 0; row < (*theList)->dataBounds.bottom; row++ )
  526.         {
  527.             c.h = col;
  528.             c.v = row;
  529.             len = sizeof( IconInfo );
  530.             
  531.             LGetCell( &info, &len, c, theList );
  532.             
  533.             // determine the type of icon and release it
  534.             
  535.             if ( info.theIcon )
  536.             {
  537.                 switch( info.iType )
  538.                 {
  539.                     case IconPlain:
  540.                         ReleaseResource( info.theIcon );
  541.                         break;
  542.                     case IconColour:
  543.                         DisposeCIcon((CIconHandle) info.theIcon );    
  544.                         break;
  545.                     case IconSuite:
  546.                         DisposeIconSuite( info.theIcon, TRUE );
  547.                         break;
  548.                 }
  549.             }
  550.         }
  551.     }
  552. }
  553.  
  554. #pragma mark -
  555. #pragma mark ======= Embedded LDEF ======
  556.  
  557.  
  558. /*----------------------------***  IconListBoxDefProc  ***------------------------------*/
  559.  
  560. static pascal void    IconListBoxDefProc( short iMessage,
  561.                                         Boolean selected,
  562.                                         Rect* bounds,
  563.                                         Cell theCell, 
  564.                                         short dataOffset,
  565.                                         short dataLength,
  566.                                         ListHandle theList )
  567. {
  568.     ZIconListBox*    zb = (ZIconListBox*)(*theList)->refCon;
  569.     IconInfo        info;
  570.     
  571.     switch( iMessage )
  572.     {
  573.         case lInitMsg:
  574.             break;
  575.         
  576.         case lDrawMsg:
  577.         case lHiliteMsg:
  578.             // set up a pointer to the list's cell data
  579.             
  580.             if ( dataLength > 0 )
  581.             {
  582.                 LGetCell( &info, &dataLength, theCell, theList );
  583.                 DrawIconCell(    bounds,
  584.                                 &info,
  585.                                 selected,
  586.                                 zb->ShowTitles(),
  587.                                 zb->GetHiliteStyle());
  588.             }
  589.             break;
  590.         
  591.         case lCloseMsg:
  592.             break;
  593.     }
  594. }
  595.  
  596.  
  597.  
  598. static void        DrawIconCell( Rect* r, IconInfo* info, Boolean hilited, Boolean showTitles, IconHilite hStyle )
  599. {
  600.     // draw the icon in the rectangle, applying information from info, etc
  601.     
  602.     Rect        ir = { 0, 0, 32, 32 };
  603.     short        iconTransform;
  604.     RGBColor    sbk;
  605.     
  606.     GetBackColor( &sbk );
  607.     BackColor( whiteColor );
  608.     EraseRect( r );
  609.     // centre the icon's rect horizontally in the cell
  610.     
  611.     OffsetRect( &ir, ((r->left + r->right) / 2) - (( ir.right - ir.left ) / 2), r->top + 1 );
  612.     
  613.     // set up the icon transform based on the selection options set
  614.     
  615.     if (hilited && (hStyle & iconHiliteDarken))
  616.         iconTransform = ttSelected;
  617.     else
  618.         iconTransform = ttNone;
  619.     
  620.     // plot the icon according to its type
  621.     
  622.     switch ( info->iType )
  623.     {
  624.         case IconIndexed:
  625.             PlotIconID( &ir, atNone, iconTransform, info->iconID );
  626.             break;
  627.         
  628.         case IconPlain:
  629.             if (info->theIcon)
  630.             {
  631.                 LoadResource( info->theIcon );
  632.                 PlotIcon( &ir, info->theIcon );
  633.                 
  634.                 if (hilited)
  635.                     InvertRect( &ir );    
  636.             }
  637.             break;
  638.         
  639.         case IconColour:
  640.             if (info->theIcon)
  641.             {
  642.                 // for these icons, the rect may not be 32 x 32, so we need to get the real
  643.                 // size and centre it accordingly.
  644.                 
  645.                 CIconHandle    ci = (CIconHandle) info->theIcon; 
  646.                 
  647.                 ir = (*ci)->iconPMap.bounds;
  648.                 OffsetRect( &ir, -ir.left, -ir.top );
  649.                 OffsetRect( &ir, ((r->left + r->right) / 2) - (( ir.right - ir.left ) / 2),
  650.                             r->top + 33 - ir.bottom - ir.top );
  651.                 
  652.                 PlotCIconHandle( &ir, atNone, iconTransform, ci );
  653.             }
  654.             break;
  655.             
  656.         default:
  657.             break;
  658.     }    
  659.     
  660.     // if we want bold border as well, draw it. Actually, this is pretty dismal looking
  661.     // and I can't imagine why anyone would want it! You have been warned!
  662.     
  663.     if ( hStyle & iconHiliteBoldBorder )
  664.     {
  665.         InsetRect( &ir, -4, -4 );
  666.         PenSize( 3, 3 );
  667.         
  668.         if (hilited)
  669.             PenMode( patOr );
  670.         else
  671.             PenMode( patBic );
  672.         
  673.         FrameRect( &ir );    
  674.     }
  675.     
  676.     // draw the icon title if required
  677.     
  678.     if ( showTitles )
  679.     {
  680.         FontInfo    fi;
  681.         GetFontInfo( &fi );
  682.         
  683.         short    tLen = StringWidth( info->title );
  684.         
  685.         MoveTo(((r->left + r->right) / 2) - (tLen / 2),  r->top + 33 + fi.ascent );
  686.         
  687.         if (hilited && ( hStyle & iconHiliteInvertTitle))
  688.             TextMode( notSrcCopy );
  689.         else
  690.             TextMode( srcCopy );
  691.         
  692.         DrawString( info->title );
  693.         TextMode( srcOr );
  694.     }
  695.     
  696.     RGBBackColor( &sbk );
  697. }
  698.  
  699. #pragma mark -
  700. #pragma mark ===== ZScrollingTextBox =====
  701.  
  702.  
  703. static pascal void    ScrollProc( ControlHandle ch, short partCode );
  704.  
  705. static ControlActionUPP    gSBarActionUPP = NewControlActionProc( ScrollProc );
  706.  
  707. /*-------------------------------***  CONSTRUCTOR  ***----------------------------------*/
  708.  
  709.  
  710. ZScrollingTextBox::ZScrollingTextBox( ZDialog* aDialog, short item )
  711.     : ZDialogItem( aDialog, item )
  712. {
  713.     te = NULL;
  714.     scroll = NULL;
  715.     editable = FALSE;
  716.     resID = 0;
  717. }
  718.  
  719. /*-------------------------------***  DESTRUCTOR  ***-----------------------------------*/
  720.  
  721.  
  722. ZScrollingTextBox::~ZScrollingTextBox()
  723. {
  724.     if ( te )
  725.         TEDispose( te );
  726.         
  727.     if ( scroll )
  728.         DisposeControl( scroll );
  729. }
  730.  
  731. /*---------------------------------***  INITITEM  ***-----------------------------------*/
  732. /*    
  733. set up the textbox item
  734. ----------------------------------------------------------------------------------------*/
  735.  
  736. void        ZScrollingTextBox::InitItem( const long param1, const long param2 )
  737. {
  738.     resID = LoWord( param1 );
  739.     editable = ( param2 != 0 );
  740.     
  741.     // get the lineheight and page height of the text
  742.     
  743.     FontInfo    fi;
  744.     
  745.     GetFontInfo( &fi );
  746.     lineHeight = fi.ascent + fi.descent + fi.leading;
  747.     pageHeight = bounds.bottom - bounds.top - lineHeight;
  748.     
  749.     // construct the mac stuff
  750.     
  751.     MakeMacTEAndScroll();
  752.     
  753.     // load the initial text
  754.     
  755.     PreloadText();
  756.     
  757.     // if the text is ediable, we can be the handler too
  758.     
  759.     canBeHandler = editable;
  760. }
  761.  
  762. /*---------------------------------***  DRAWITEM  ***-----------------------------------*/
  763. /*    
  764. refresh the item
  765. ----------------------------------------------------------------------------------------*/
  766.  
  767. void        ZScrollingTextBox::DrawItem()
  768. {
  769.     Rect                ir = bounds;
  770.     ZAdvancedDialog*    zd = (ZAdvancedDialog*) GetBoss();
  771.     
  772.     InsetRect( &ir, 1, 1 );
  773.     ir.right -= kStdScrollbarWidth;
  774.     EraseRect( &ir );
  775.     
  776.     TEUpdate( &bounds, te );
  777.     FrameRect( &bounds );
  778.     
  779.     #ifdef _GREYSCALE_APPEARANCE
  780.     
  781.     zd->SetDefaultColours();
  782.     FrameGrayRect( &bounds );
  783.     
  784.     #endif
  785.     
  786.     // draw a border if we are the handler and the owner can have more than
  787.     // just this item as the keyboard focus
  788.     
  789.     if ( isHandler && zd->HasMultipleFoci())
  790.         DrawBorder( TRUE );
  791. }
  792.  
  793. /*---------------------------------***  CLICKITEM  ***----------------------------------*/
  794. /*    
  795. handle mouse click in item
  796. ----------------------------------------------------------------------------------------*/
  797.  
  798. void        ZScrollingTextBox::ClickItem( const Point where, const short modifiers )
  799. {
  800.     if ( enabled )
  801.     {
  802.         // make sure this is the handler when clicked
  803.         
  804.         if (! isHandler && canBeHandler)
  805.             BecomeHandler( TRUE );
  806.         
  807.         // detect and handle click in scrollbar
  808.         
  809.         if ( PtInScrollbar( where ))
  810.         {
  811.             short            partCode;
  812.             ControlHandle    ch;
  813.             ZDialog*        zd = (ZDialog*) GetBoss();
  814.             
  815.             partCode = FindControl( where, zd->GetMacWindow(), &ch );
  816.             
  817.             if ( partCode > 0 )
  818.             {
  819.                 if ( partCode == kControlIndicatorPart )
  820.                 {
  821.                     short    delta = GetControlValue( scroll );
  822.                     
  823.                     partCode = TrackControl( scroll, where, NULL );
  824.                     
  825.                     if ( partCode == kControlIndicatorPart )
  826.                     {
  827.                         delta -= GetControlValue( scroll );
  828.                     
  829.                         Scroll( delta );
  830.                     }
  831.                 }
  832.                 else
  833.                     partCode = TrackControl( scroll, where, gSBarActionUPP );
  834.             }
  835.         }
  836.         else
  837.         {
  838.             if ( editable )
  839.             {
  840.                 TEClick( where, modifiers & shiftKey, te );
  841.                 CalScroll();
  842.             }
  843.         }
  844.     }
  845. }
  846.  
  847. /*-------------------------------***  ADJUSTCURSOR  ***---------------------------------*/
  848. /*    
  849. set cursor to i-beam over editable text
  850. ----------------------------------------------------------------------------------------*/
  851.  
  852. void        ZScrollingTextBox::AdjustCursor( const Point where, const short modifiers )
  853. {
  854.     if ( PtInScrollbar( where ))
  855.         SetCursorShape( 0 );
  856.     else
  857.     {
  858.         if ( editable )
  859.             SetCursorShape( iBeamCursor );
  860.     }
  861. }
  862.  
  863. /*---------------------------------***  ACTIVATE  ***-----------------------------------*/
  864. /*    
  865. activate/deactivate the text
  866. ----------------------------------------------------------------------------------------*/
  867.  
  868. void        ZScrollingTextBox::Activate( const Boolean isActive )
  869. {
  870.     ZAdvancedDialog* zd = (ZAdvancedDialog*) GetBoss();
  871.     
  872.     if ( isHandler && zd->HasMultipleFoci())
  873.         DrawBorder( isActive );
  874.  
  875.     if ( editable )
  876.     {
  877.         ZGrafState    zg;
  878.         
  879.         SetUpFontAndColours();
  880.         
  881.         if ( isActive )
  882.             TEActivate( te );
  883.         else
  884.             TEDeactivate( te );
  885.             
  886.         if ( gFontMenuID )
  887.         {
  888.             if ( isHandler && isActive )
  889.                 gMenuBar->EnableCommand( gFontMenuID, 0 );
  890.             else
  891.                 gMenuBar->DisableCommand( gFontMenuID, 0 );
  892.         }    
  893.     }
  894. }
  895.  
  896. /*-----------------------------***  BECOMEHANDLER  ***----------------------------------*/
  897. /*    
  898. become the current keyboard handler
  899. ----------------------------------------------------------------------------------------*/
  900.  
  901. void        ZScrollingTextBox::BecomeHandler( Boolean isBecoming )
  902. {
  903.     ZDialogItem::BecomeHandler( isBecoming );
  904.     
  905.     if ( editable )
  906.         Activate( isHandler );
  907. }
  908.  
  909.  
  910. /*---------------------------------***  HILITE  ***-------------------------------------*/
  911. /*    
  912. set hilite state of scrollbar
  913. ----------------------------------------------------------------------------------------*/
  914.  
  915. void        ZScrollingTextBox::Hilite( Boolean state )
  916. {
  917.     HiliteControl( scroll, state? 0 : 255 );
  918. }
  919.  
  920.  
  921. /*----------------------------------***  DOCUT  ***-------------------------------------*/
  922. /*    
  923. handle the Cut command
  924. ----------------------------------------------------------------------------------------*/
  925.  
  926. void        ZScrollingTextBox::DoCut()
  927. {
  928.     if ( editable )
  929.     {
  930.         ZGrafState    zg;
  931.         
  932.         SetUpFontAndColours();
  933.         TECut( te );
  934.         CalScroll();
  935.     }
  936. }
  937.  
  938. /*----------------------------------***  DOCOPY  ***------------------------------------*/
  939. /*    
  940. handle the Copy command
  941. ----------------------------------------------------------------------------------------*/
  942.  
  943. void        ZScrollingTextBox::DoCopy()
  944. {
  945.     if ( editable )
  946.         TECopy( te );
  947. }
  948.  
  949. /*---------------------------------***  DOPASTE  ***------------------------------------*/
  950. /*    
  951. handle the Paste command
  952. ----------------------------------------------------------------------------------------*/
  953.  
  954. void        ZScrollingTextBox::DoPaste()
  955. {
  956.     if ( editable )
  957.     {
  958.         ZGrafState    zg;
  959.         
  960.         SetUpFontAndColours();
  961.         TEStylePaste( te );
  962.         CalScroll();
  963.     }
  964. }
  965.  
  966. /*---------------------------------***  DOCLEAR  ***------------------------------------*/
  967. /*    
  968. handle the Clear command
  969. ----------------------------------------------------------------------------------------*/
  970.  
  971. void        ZScrollingTextBox::DoClear()
  972. {
  973.     if ( editable )
  974.     {
  975.         ZGrafState    zg;
  976.         
  977.         SetUpFontAndColours();
  978.         TEDelete( te );
  979.         CalScroll();
  980.     }
  981. }
  982.  
  983.  
  984. /*-------------------------------***  DOSELECTALL  ***----------------------------------*/
  985. /*    
  986. handle the Select All command
  987. ----------------------------------------------------------------------------------------*/
  988.  
  989. void        ZScrollingTextBox::DoSelectAll()
  990. {
  991.     if ( editable )
  992.     {
  993.         ZGrafState    zg;
  994.         
  995.         SetUpFontAndColours();
  996.         TESetSelect( 0, 32767, te );
  997.     }
  998. }
  999.  
  1000.  
  1001. /*-------------------------------***  CANPASTETYPE  ***---------------------------------*/
  1002. /*    
  1003. see if there is pasteable data on the clipboard- we can handle TEXT.
  1004. ----------------------------------------------------------------------------------------*/
  1005.  
  1006. Boolean        ZScrollingTextBox::CanPasteType()
  1007. {
  1008.     return gClipboard->QueryType( 'TEXT' );
  1009. }
  1010.  
  1011.  
  1012. /*-------------------------------***  UPDATEMENUS  ***----------------------------------*/
  1013. /*    
  1014. update edit menu commands for this item where appropriate
  1015. ----------------------------------------------------------------------------------------*/
  1016.  
  1017. void        ZScrollingTextBox::UpdateMenus()
  1018. {
  1019.     if ( editable )
  1020.     {
  1021.         if ((*te)->selStart < (*te)->selEnd )
  1022.         {
  1023.             gMenuBar->EnableCommand( kCmdCut );    
  1024.             gMenuBar->EnableCommand( kCmdCopy );    
  1025.             gMenuBar->EnableCommand( kCmdClear );    
  1026.         }
  1027.         
  1028.         gMenuBar->EnableCommand( kCmdSelectAll );
  1029.         
  1030.         // Font/style menus:
  1031.         
  1032.         TEStyleRunInfo    ri;
  1033.         
  1034.         TEGetStyleRunInfo( &ri, te );
  1035.             
  1036.         gMenuBar->UpdateFontSizeMenu( &ri );
  1037.         gMenuBar->UpdateStyleMenu( &ri );
  1038.     }
  1039.     
  1040.     ZDialogItem::UpdateMenus();
  1041. }
  1042.  
  1043.  
  1044. /*------------------------------***  HANDLECOMMAND  ***---------------------------------*/
  1045. /*    
  1046. handle font menu
  1047. ----------------------------------------------------------------------------------------*/
  1048.  
  1049. void        ZScrollingTextBox::HandleCommand( const long aCmd )
  1050. {
  1051.     // handle font size and style commands
  1052.     
  1053.     TextStyle        newStyle;
  1054.     Boolean            wasChanged = TRUE;
  1055.     ZGrafState        zg;
  1056.  
  1057.     SetUpFontAndColours();
  1058.     
  1059.     switch( aCmd )
  1060.     {
  1061.         case kCmdPlainText:
  1062.             newStyle.tsFace = normal;
  1063.             TESetStyle( doFace, &newStyle, true, te );
  1064.             break;
  1065.         
  1066.         case kCmdBoldText:
  1067.             newStyle.tsFace = bold;
  1068.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1069.             break;
  1070.         
  1071.         case kCmdItalicText:
  1072.             newStyle.tsFace = italic;
  1073.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1074.             break;
  1075.         
  1076.         case kCmdUnderlineText:
  1077.             newStyle.tsFace = underline;
  1078.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1079.             break;
  1080.         
  1081.         case kCmdOutlineText:
  1082.             newStyle.tsFace = outline;
  1083.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1084.             break;
  1085.         
  1086.         case kCmdShadowText:
  1087.             newStyle.tsFace = shadow;
  1088.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1089.             break;
  1090.         
  1091.         case kCmdCondensedText:
  1092.             newStyle.tsFace = condense;
  1093.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1094.             break;
  1095.         
  1096.         case kCmdExtendedText:
  1097.             newStyle.tsFace = extend;
  1098.             TESetStyle( doFace + doToggle, &newStyle, true, te );
  1099.             break;
  1100.         
  1101.         case kCmdStdFontSize9:
  1102.         case kCmdStdFontSize10:
  1103.         case kCmdStdFontSize12:
  1104.         case kCmdStdFontSize14:
  1105.         case kCmdStdFontSize18:
  1106.         case kCmdStdFontSize24:
  1107.         case kCmdStdFontSize36:
  1108.         case kCmdStdFontSize48:
  1109.         case kCmdStdFontSize60:
  1110.         case kCmdStdFontSize72:
  1111.             newStyle.tsSize = aCmd - kStdFontSizeBase;
  1112.             TESetStyle( doSize, &newStyle, true, te );
  1113.             break;
  1114.                 
  1115.         default:
  1116.             ZDialogItem::HandleCommand( aCmd );
  1117.             wasChanged = FALSE;
  1118.             break;
  1119.     }
  1120.     
  1121.     if ( wasChanged )
  1122.         CalScroll();
  1123. }
  1124.  
  1125.  
  1126. /*------------------------------***  HANDLECOMMAND  ***---------------------------------*/
  1127.  
  1128.  
  1129. void        ZScrollingTextBox::HandleCommand( const short menuID, const short itemID )
  1130. {
  1131.     if ( menuID == gFontMenuID && editable )
  1132.     {
  1133.         ZGrafState    zg;
  1134.         
  1135.         Str255        itemName;
  1136.         TextStyle    newStyle;
  1137.         
  1138.         SetUpFontAndColours();
  1139.         GetMenuItemText( GetMenuHandle( gFontMenuID ), itemID, itemName );
  1140.         GetFNum( itemName, &newStyle.tsFont );
  1141.         TESetStyle( doFont, &newStyle, true, te );
  1142.         CalScroll();
  1143.     }
  1144.     else
  1145.         ZDialogItem::HandleCommand( menuID, itemID );
  1146. }
  1147.  
  1148.  
  1149. /*-----------------------------------***  TYPE  ***-------------------------------------*/
  1150. /*    
  1151. type text if editable
  1152. ----------------------------------------------------------------------------------------*/
  1153.  
  1154. void        ZScrollingTextBox::Type( const char theKey, const short modifiers )
  1155. {
  1156.     ZDialogItem::Type( theKey, modifiers );
  1157.     
  1158.     if ( editable && ( theKey != 0x09 ))
  1159.     {
  1160.         ZGrafState    zg;
  1161.         
  1162.         SetUpFontAndColours();
  1163.         TEKey( theKey, te );
  1164.         CalScroll();
  1165.     }
  1166. }
  1167.  
  1168. /*-----------------------------------***  IDLE  ***-------------------------------------*/
  1169. /*    
  1170. blink cursor in editable text
  1171. ----------------------------------------------------------------------------------------*/
  1172.  
  1173. void        ZScrollingTextBox::Idle()
  1174. {
  1175.     if ( editable && isHandler )
  1176.         TEIdle( te );
  1177.         
  1178.     ZDialogItem::Idle();
  1179. }
  1180.  
  1181. /*----------------------------------***  SETTEXT  ***-----------------------------------*/
  1182. /*    
  1183. set the item's text
  1184. ----------------------------------------------------------------------------------------*/
  1185.  
  1186. void        ZScrollingTextBox::SetText( Handle textH, Handle styleH )
  1187. {
  1188.     FailOSErr(( textH == NULL )? paramErr : noErr );
  1189.     
  1190.     long    tLen = GetHandleSize( textH );
  1191.     
  1192.     TEActivate( te );
  1193.     TESetSelect( 0, 32767, te );
  1194.     TEDelete( te );
  1195.     
  1196.     HLock( textH );
  1197.     TEStyleInsert( *textH, tLen, (StScrpHandle) styleH, te );
  1198.     HUnlock( textH );
  1199.     
  1200.     TESetSelect( 0, 0, te );
  1201.     TEDeactivate( te );
  1202.         
  1203.     CalScroll();
  1204. }
  1205.  
  1206. /*----------------------------------***  GETTEXT  ***-----------------------------------*/
  1207. /*    
  1208. get the text. This copies the text (and optionally the style) into the handles passed,
  1209. resizing them as needed and replacing any existing data therein.
  1210. ----------------------------------------------------------------------------------------*/
  1211.  
  1212. void        ZScrollingTextBox::GetText( Handle textH, Handle styleH )
  1213. {
  1214.     FailOSErr(( textH == NULL )? paramErr : noErr );
  1215.     
  1216.     char            hs = HGetState((*te)->hText);
  1217.     StScrpHandle    st = NULL;
  1218.     short            se, ss;
  1219.     
  1220.     HLock((*te)->hText);
  1221.     
  1222.     try
  1223.     {
  1224.         FailOSErr( PtrToXHand( *(*te)->hText, textH, (*te)->teLength ));
  1225.         
  1226.         // if the styleH is not NULL, get the style handle too
  1227.         
  1228.         if ( styleH )
  1229.         {
  1230.             se = (*te)->selEnd;
  1231.             ss = (*te)->selStart;
  1232.             
  1233.             TESetSelect( 0, 32767, te );
  1234.             
  1235.             st = TEGetStyleScrapHandle( te );
  1236.         
  1237.             if ( st )
  1238.             {
  1239.                 HLock((Handle) st );
  1240.             
  1241.                 FailOSErr( PtrToXHand( *st, styleH, GetHandleSize((Handle) st )));
  1242.             
  1243.                 HUnlock((Handle) st );
  1244.                 DisposeHandle((Handle) st );
  1245.             }
  1246.             
  1247.             TESetSelect( ss, se, te );
  1248.         }    
  1249.     }
  1250.     catch( OSErr err )
  1251.     {
  1252.         HSetState((*te)->hText, hs );
  1253.         
  1254.         if ( st )
  1255.         {
  1256.             DisposeHandle((Handle) st );
  1257.             TESetSelect( ss, se, te );
  1258.         }
  1259.         
  1260.         throw err;
  1261.     }
  1262.     
  1263.     HSetState((*te)->hText, hs );
  1264. }
  1265.  
  1266.  
  1267. /*---------------------------***  MAKEMACTEANDSCROLL  ***-------------------------------*/
  1268. /*    
  1269. create the textedit record and scrollbar
  1270. ----------------------------------------------------------------------------------------*/
  1271.  
  1272. void        ZScrollingTextBox::MakeMacTEAndScroll()
  1273. {
  1274.     Rect        rView;
  1275.     ZDialog*    zd;
  1276.     WindowPtr    w;
  1277.     
  1278.     zd = (ZDialog*) GetBoss();
  1279.     w = zd->GetMacWindow();
  1280.     
  1281.     rView = bounds;
  1282.     rView.right -= kStdScrollbarWidth;            // allow for scrollbar's width
  1283.     InsetRect( &rView, 3, 3 );
  1284.     
  1285.     FailNIL( te = TEStyleNew( &rView, &rView ));
  1286.     TECalText( te );
  1287.     
  1288.     // make the scrollbar
  1289.     
  1290.     rView = bounds;
  1291.     rView.left = rView.right - 16;
  1292.     
  1293.     FailNIL( scroll = NewControl( w, &rView, NULL, TRUE, 0, 0, 0, scrollBarProc, (long) this ));
  1294.  
  1295.     TEAutoView( TRUE, te );
  1296. }
  1297.  
  1298. /*-------------------------------***  PRELOADTEXT  ***----------------------------------*/
  1299. /*    
  1300. install text from resource
  1301. ----------------------------------------------------------------------------------------*/
  1302.  
  1303. void        ZScrollingTextBox::PreloadText()
  1304. {
  1305.     Handle t, s;
  1306.     
  1307.     if ( resID > 0 )
  1308.     {
  1309.         t = GetResource( 'TEXT', resID );
  1310.         
  1311.         if ( t )
  1312.         {
  1313.             s = GetResource( 'styl', resID );
  1314.     
  1315.             SetText( t, s );
  1316.         
  1317.             if ( s )
  1318.                 ReleaseResource ( s );
  1319.                 
  1320.             ReleaseResource( t );
  1321.         }
  1322.     }
  1323. }
  1324.  
  1325.  
  1326. /*--------------------------------***  CALSCROLL  ***-----------------------------------*/
  1327. /*    
  1328. adjust scrollbar max according to amount of text and height of box, etc.
  1329. ----------------------------------------------------------------------------------------*/
  1330.  
  1331. void        ZScrollingTextBox::CalScroll()
  1332. {
  1333.     short     tHeight = TEGetHeight( 32767, 0, te );
  1334.     short    sMax;
  1335.     
  1336.     // scrollbar max is set to the height of the lines less the height of bounds
  1337.     
  1338.     sMax = tHeight - ( bounds.bottom - bounds.top - 6 );
  1339.     
  1340.     if ( sMax < 0 )
  1341.         sMax = 0;
  1342.     
  1343.     SetControlMaximum( scroll, sMax ); 
  1344.     
  1345.     // compute value
  1346.     
  1347.     sMax = (*te)->viewRect.top - (*te)->destRect.top;
  1348.     
  1349.     SetControlValue( scroll, sMax );    
  1350. }
  1351.  
  1352.  
  1353. Boolean        ZScrollingTextBox::PtInScrollbar( const Point mouse )
  1354. {
  1355.     Rect    r = bounds;
  1356.     
  1357.     r.left = r.right - 15;
  1358.     
  1359.     return PtInRect( mouse, &r );
  1360. }
  1361.  
  1362.  
  1363.  
  1364. void        ZScrollingTextBox::Scroll( short delta )
  1365. {
  1366.     TEScroll( 0, delta, te );
  1367. }
  1368.  
  1369.  
  1370. void        ZScrollingTextBox::DoScroll( short partCode )
  1371. {
  1372.     short sDelta = 0;
  1373.     
  1374.     switch ( partCode )
  1375.     {
  1376.         case kControlUpButtonPart:
  1377.             sDelta = -lineHeight;
  1378.             break;
  1379.         
  1380.         case kControlDownButtonPart:
  1381.             sDelta = lineHeight;
  1382.             break;
  1383.         
  1384.         case kControlPageUpPart:
  1385.             sDelta = -pageHeight;
  1386.             break;
  1387.         
  1388.         case kControlPageDownPart:
  1389.             sDelta = pageHeight;
  1390.             break;
  1391.     }
  1392.     
  1393.     short    sv = GetControlValue( scroll );
  1394.     
  1395.     SetControlValue( scroll, sv + sDelta );
  1396.     sDelta = sv - GetControlValue( scroll );
  1397.     
  1398.     Scroll( sDelta );
  1399. }
  1400.  
  1401.  
  1402. static pascal void    ScrollProc( ControlHandle ch, short partCode )
  1403. {
  1404.     ZScrollingTextBox*    zi = (ZScrollingTextBox*) GetControlReference( ch );
  1405.  
  1406.     if ( zi )
  1407.         zi->DoScroll( partCode );
  1408. }